#ifndef __H__BASESHAPE__
#define __H__BASESHAPE__
#include <glut.h>
#include <cmath>
#include <string>

extern const GLdouble TurnAngle;
class baseShape
{
protected:
	GLint m_lists;
	GLsizei m_listlen;
	int inited;
	
	GLdouble m_Point;
	int m_haveShadow;
	GLdouble m_Speed[3];//SpeedX SpeedY SpeedZ  meters/second
public:
	GLdouble m_Position[3];
	baseShape()
	{
		inited=0;
		m_lists=0;m_listlen=0;
		m_Point=0;
		m_haveShadow=0;
		memset(m_Speed,0,sizeof(m_Speed));
		memset(m_Position,0,sizeof(m_Position));
	}

	~baseShape()
	{
		if(m_listlen)glDeleteLists(m_lists,m_listlen);
	}

	virtual void draw()
	{
		if(m_haveShadow)
		{
			glPushMatrix();
			glTranslated(m_Position[0],m_Position[1],0);
			glCallList(m_lists+m_listlen);
			glPopMatrix();
		}

		glPushMatrix();
		glMatrixMode(GL_MODELVIEW);
		glTranslated(m_Position[0],m_Position[1],m_Position[2]);
		glRotated(m_Point,0,0,1);
		glCallLists(m_listlen,GL_INT,&m_lists);
		glPopMatrix();	
	}

	virtual void xSpeedUp()//forward 
	{
		m_Speed[0]+=.2f;
	}

	virtual void xSpeedDown()
	{
		m_Speed[0]-=.2f;
	}

	virtual void ySpeedUp()
	{
		m_Speed[1]+=.2f;
	}

	virtual void ySpeedDown()
	{
		m_Speed[1]-=.2f;
	}

	virtual void zSpeedUp()
	{
		m_Speed[2]+=.2f;
	}

	virtual void zSpeedDown()
	{
		m_Speed[2]-=.2f;
	}

	virtual void MoveZ(float millisec)//up and down
	{
	
		if((m_Position[2]+=m_Speed[2]*(millisec/1000.0))<=0)
		{
			m_Position[2]=0;
			m_Speed[2]=0;
		}
		
	}

	virtual void MoveY(float millisec)//left and right
	{
		m_Position[0]+=cos(-m_Point/180*M_PI)*m_Speed[1]*(millisec/1000.0);
		m_Position[1]-=sin(-m_Point/180*M_PI)*m_Speed[1]*(millisec/1000.0);
	}

	virtual void MoveX(float millisec)//forward and backward
	{
		m_Position[1]-=cos(-m_Point/180*M_PI)*m_Speed[0]*(millisec/1000.0);
		m_Position[0]-=sin(-m_Point/180*M_PI)*m_Speed[0]*(millisec/1000.0);
	}

	virtual void TurnLeft()
	{
		m_Point+=TurnAngle;
	}

	virtual void TrunRight()
	{
		m_Point-=TurnAngle;
	}

	virtual void init()=0;

	static void setNormal(const GLdouble v1[3],const GLdouble v2[3],const GLdouble v3[3]) 
	{

		const GLdouble s1[] = {v2[0]-v1[0], v2[1]-v1[1], v2[2]-v1[2]};
		const GLdouble s2[] = {v3[0]-v1[0], v3[1]-v1[1], v3[2]-v1[2]};

		GLdouble n[] = {
			s1[1]*s2[2] - s1[2]*s2[1],
			s1[2]*s2[0] - s1[0]*s2[2],
			s1[0]*s2[1] - s1[1]*s2[0]
		};

		GLdouble abs = -sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
		n[0] /= abs;
		n[1] /= abs;
		n[2] /= abs;


		glNormal3dv(n);
	}

	static void setNormal(
		const GLdouble &p1x,
		const GLdouble &p1y,
		const GLdouble &p1z,
		const GLdouble &p2x,
		const GLdouble &p2y,
		const GLdouble &p2z,
		const GLdouble &p3x,
		const GLdouble &p3y,
		const GLdouble &p3z) 
	{

		const GLdouble v1[]={p1x,p1y,p1z},
			v2[]={p2x,p2y,p2z},
			v3[]={p3x,p3y,p3z};
		const GLdouble s1[] = {v2[0]-v1[0], v2[1]-v1[1], v2[2]-v1[2]};
		const GLdouble s2[] = {v3[0]-v1[0], v3[1]-v1[1], v3[2]-v1[2]};

		GLdouble n[] = {
			s1[1]*s2[2] - s1[2]*s2[1],
			s1[2]*s2[0] - s1[0]*s2[2],
			s1[0]*s2[1] - s1[1]*s2[0]
		};

		GLdouble abs = -sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
		n[0] /= abs;
		n[1] /= abs;
		n[2] /= abs;


		glNormal3dv(n);
	}

	virtual void OnTimer(int millisec)
	{
		MoveX(millisec);
		MoveY(millisec);
		MoveZ(millisec);
	}

	const GLdouble GetSpeedX() const
	{
		return m_Speed[0];
	}

	const GLdouble GetSpeedY() const
	{
		return m_Speed[1];
	}

	const GLdouble GetSpeedZ() const
	{
		return m_Speed[2];
	}
};
#endif